import EventHandler from "./EventHandler";

export default class EventDispatcher {
    public _events;
    public hasListener(e) {
        return !(!this._events || !this._events[e]);
    };
    public event(e, t) {
        void 0 === t && (t = null);
        if (!this._events || !this._events[e]) return false;
        var a = this._events[e];
        if (a.run) {
            a.once && delete this._events[e];
            a.check(this, e) && (null != t ? a.runWith(t) : a.run());
        } else {
            for (var o = 0, i = a.length; o < i; o++) {
                var r = a[o];
                r && r.check(this, e) && (null != t ? r.runWith(t) : r.run());
                if (!r || r.once) {
                    a.splice(o, 1);
                    o--;
                    i--;
                }
            }
            0 === a.length && this._events && delete this._events[e];
        }
        return true;
    };
    public on(e, t, a, o) {
        void 0 === o && (o = null);
        return this._createListener(e, t, a, o, false);
    };
    public once(e, t, a, o) {
        void 0 === o && (o = null);
        return this._createListener(e, t, a, o, true);
    };
    public _createListener(e, t, a, i, r, n?) {
        void 0 === n && (n = true);
        n && this.off(e, t, a, r);
        var l = EventHandler.create(t || this, a, i, r);
        if(!l.register){
            debugger;
        }
        l.register(this, e);
     
        this._events || (this._events = {});
        var s = this._events;
        s[e] ? s[e].run ? s[e] = [s[e], l] : s[e].push(l) : s[e] = l;
        return this;
    };
    public off(e, t, a, o?) {
        void 0 === o && (o = false);
        if (!this._events || !this._events[e]) return this;
        var i = this._events[e];
        if (null != i) if (i.run) {
            if ((!t || i.caller === t) && (null == a || i.method === a) && (!o || i.once)) {
                delete this._events[e];
                i.recover();
            }
        } else {
            for (var r = 0, n = i.length, l = 0; l < n; l++) {
                var s = i[l];
                if (s) {
                    if (s && (!t || s.caller === t) && (null == a || s.method === a) && (!o || s.once)) {
                        r++;
                        i[l] = "NULL";
                        s.recover();
                    }
                } else {
                    i[l] = "NULL";
                    r++;
                }
            }
            if (r === n) delete this._events[e]; else if (r > 0) {
                for (var c = 0, u = 0; u < n; ++u) {
                    var p = i[u];
                    if (null == p) {
                        i.splice(u);
                        break;
                    }
                    if ("NULL" == p) i[u] = null; else {
                        if (u != c) {
                            i[c] = p;
                            i[u] = null;
                        }
                        ++c;
                    }
                }
                i.length = n - r;
            }
        }
        return this;
    };
    public offAll(e) {
        void 0 === e && (e = null);
        var t = this._events;
        if (!t) return this;
        if (e) {
            this._recoverHandlers(t[e]);
            delete t[e];
        } else {
            for (var a in t) this._recoverHandlers(t[a]);
            this._events = null;
        }
        return this;
    };
    public offAllCaller(e) {
        if (e && this._events) for (var t in this._events) this.off(t, e, null);
        return this;
    };
    public _recoverHandlers(e) {
        if (e) if (e.run) e.recover(); else for (var t = e.length - 1; t > -1; t--) if (e[t]) {
            e[t].recover();
            e[t] = null;
        }
    };
}
